home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / ted5.zip / MENU.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  38KB  |  1,878 lines

  1. /////////////////////////////////////////////////////////////////
  2. //
  3. // Pull-Down Menu Interface
  4. // by John Romero (C) 1991 Id Software
  5. //
  6. /////////////////////////////////////////////////////////////////
  7. #include "ted5.h"
  8. #pragma hdrstop
  9.  
  10. #define NUMFLASHES    10
  11. #define ALT        0x38
  12. #define CTRL        0x1d
  13.  
  14. #define CGASIZE        0x4000
  15. #define EGA1SIZE    0x2000
  16. #define EGA2SIZE    0x9600
  17. #define EGA3SIZE    60000
  18. #define VGASIZE        64000
  19.  
  20. void (*HookRoutine)(int x,int y);
  21. void (*ItemRoutine)(void);
  22. char MenuStr[20][80],tempstr[80];
  23. memptr Background[10];
  24. int WhichBack;
  25. struct { int savex,savey,savew,saveh;  } Back[10];
  26. MBarDef *MBarPtr;
  27. MInfoType MenuInfo[10];
  28. int ScreenWidth,OpenMenu,NumMenus,ItemOn,KeybdOn;
  29.  
  30. void HandleOpenMenu(void (*UserRoutine)(void),int which);
  31. void HandleCloseMenu(void (*UserRoutine)(void));
  32. void HandleHighlight(void (*UserRoutine)(void));
  33. int  DetectMenu(int x,int y);
  34. void ChangeItem(int newitem);
  35. void ClearScreen(void);
  36. void RedrawDesktop(void);
  37. char *PassScancode(int sc);
  38.  
  39. /////////////////////////////////////////////////////////////////
  40. //
  41. // Desktop Event Loop
  42. //
  43. /////////////////////////////////////////////////////////////////
  44. void DeskEventLoop(void (*UserRoutine)(void),void (*ConstantRoutine)(void))
  45. {
  46.  int buttonstatus=0,oldmenu,olditem;
  47.  enum clicks {upup,updown,downup,downdown};
  48.  
  49.  if (KeybdOn)
  50.    {
  51.     HandleOpenMenu(UserRoutine,2);
  52.     ChangeItem(1);
  53.    }
  54.  
  55.  MouseShow();
  56.  while(1)
  57.    {
  58.     int temp=MouseButton()&1,temp1=(MouseButton()>>1)&1;
  59.  
  60.     sx=0;
  61.     sy=3;
  62.  
  63.     if (!OpenMenu)
  64.       ConstantRoutine();
  65.     switch(buttonstatus=((buttonstatus<<1)|temp|temp1)&3)
  66.       {
  67.        case upup: break;
  68.        case updown: HandleOpenMenu(UserRoutine,0);
  69.             break;
  70.        case downdown: HandleHighlight(UserRoutine);
  71.               break;
  72.        case downup: HandleCloseMenu(UserRoutine);
  73.             if (ItemOn && ItemRoutine)
  74.               ItemRoutine();
  75.             ItemOn=0;
  76.             break;
  77.       }
  78.  
  79.     if (bioskey(1))
  80.       {
  81.        char key=bioskey(1)>>8;
  82.        int nitems;
  83.  
  84.        if (OpenMenu)
  85.      {
  86.       bioskey(0);
  87.  
  88.       nitems=(MBarPtr+OpenMenu-1)->num_items;
  89.  
  90.       switch(key)
  91.         {
  92.          case 0x48: if (OpenMenu)
  93.               if (ItemOn)
  94.                 if (ItemOn==1)
  95.                   ChangeItem(nitems);
  96.                 else
  97.                   ChangeItem(ItemOn-1);
  98.             break;
  99.          case 0x50: if (OpenMenu)
  100.               if (ItemOn)
  101.                 if (ItemOn==nitems)
  102.                   ChangeItem(1);
  103.                 else
  104.                   ChangeItem(ItemOn+1);
  105.             break;
  106.          case 0x1c: oldmenu=OpenMenu;
  107.             olditem=ItemOn;
  108.             HandleCloseMenu(UserRoutine);
  109.             if (ItemOn)
  110.               ItemRoutine();
  111.  
  112.             break;
  113.          case 0x4b: if (OpenMenu)
  114.               {
  115.                int newmenu;
  116.  
  117.                ItemOn=0;
  118.                if (OpenMenu==1)
  119.                  newmenu=NumMenus;
  120.                else
  121.                  newmenu=OpenMenu-1;
  122.  
  123.                HandleCloseMenu(UserRoutine);
  124.                HandleOpenMenu(UserRoutine,newmenu);
  125.  
  126.                ChangeItem(1);
  127.               }
  128.             break;
  129.          case 0x4d: if (OpenMenu)
  130.               {
  131.                int newmenu;
  132.  
  133.                ItemOn=0;
  134.                if (OpenMenu==NumMenus)
  135.                  newmenu=1;
  136.                else
  137.                  newmenu=OpenMenu+1;
  138.  
  139.                HandleCloseMenu(UserRoutine);
  140.                HandleOpenMenu(UserRoutine,newmenu);
  141.  
  142.                ChangeItem(1);
  143.               }
  144.             break;
  145.          case 0x01: if (!OpenMenu)
  146.               {
  147.                HandleOpenMenu(UserRoutine,oldmenu);
  148.                ChangeItem(olditem);
  149.               }
  150.             break;
  151.         }
  152.      }
  153.        else
  154.      {
  155.       int i,j,numitems,run=0;
  156.       MenuDef *items;
  157.  
  158.       for (i=0;i<NumMenus;i++)
  159.         {
  160.          numitems=(MBarPtr+i)->num_items;
  161.          items=(MBarPtr+i)->menu_def;
  162.  
  163.          for (j=0;j<numitems;j++)
  164.            if ((items+j)->hotkey==key && (items+j)->hotkey)
  165.          {
  166.           if (((items+j)->shiftflag) &&
  167.               (!keydown[(items+j)->shiftflag]))
  168.             continue;
  169.  
  170.           ItemRoutine=(items+j)->routine;
  171.           ItemRoutine();
  172.           run=1;
  173.           break;
  174.          }
  175.          if (run)
  176.            {
  177.         if (bioskey(1))
  178.           bioskey(0);
  179.         break;
  180.            }
  181.         }
  182.       if (!run)
  183.         UserRoutine();
  184.      }
  185.       }
  186.    }
  187. }
  188.  
  189.  
  190.  
  191. /////////////////////////////////////////////////////////////////
  192. //
  193. // See if a menu was opened
  194. //
  195. /////////////////////////////////////////////////////////////////
  196. void HandleOpenMenu(void (*UserRoutine)(void),int which)
  197. {
  198.  int x,y,loop,flag,tempx,tempw,maxw,loopsize;
  199.  MenuDef *items;
  200.  
  201.  if (!which)
  202.    {
  203.     MouseCoords(&x,&y);
  204.     if (y>8 && !OpenMenu)
  205.       {
  206.        UserRoutine();
  207.        return;
  208.       }
  209.  
  210.     flag=DetectMenu(x,y);
  211.     if (!flag) return;
  212.    }
  213.  else
  214.    flag=which;
  215.  
  216.  
  217.  tempx=MenuInfo[flag-1].menux;
  218.  tempw=MenuInfo[flag-1].menuwidth;
  219.  items=(MBarPtr+flag-1)->menu_def;
  220.  
  221.  sx=tempx+1;
  222.  sy=0;
  223.  maxw=0;
  224.  
  225.  MouseHide();
  226.  
  227.  
  228.  //
  229.  // BUILD MENU STRINGS
  230.  //
  231.  loopsize=(MBarPtr+flag-1)->num_items;
  232.  
  233.  for (loop=0;loop<loopsize;loop++)
  234.    {
  235.     int len;
  236.  
  237.     memset(MenuStr[loop],0,80);
  238.  
  239.     MenuStr[loop][0]=4;    // leftedge
  240.     strcat(MenuStr[loop],(items+loop)->item_name);
  241.  
  242.     len=strlen(MenuStr[loop]);
  243.     memset(&MenuStr[loop][len],' ',tempw-len+1);
  244.  
  245.     switch((items+loop)->shiftflag)
  246.       {
  247.        case ALT: strcat(MenuStr[loop]," ALT-"); break;
  248.        case CTRL:strcat(MenuStr[loop],"CTRL-");
  249.       }
  250.  
  251.     strcat(MenuStr[loop],PassScancode((items+loop)->hotkey));
  252.  
  253.     len=strlen(MenuStr[loop]);
  254.     if (len>maxw)
  255.       maxw=len;
  256.    }
  257.  
  258.  if (tempx+maxw>ScreenWidth)
  259.    tempx=ScreenWidth-1-maxw;
  260.  SaveBackground(tempx*8,0,(maxw+1)*8,(MBarPtr+flag-1)->num_items*8+16);
  261.  
  262.  //
  263.  // PRINT MENU STRINGS
  264.  //
  265.  xormask=0xffff;
  266.  print((MBarPtr+flag-1)->menu_name);
  267.  xormask=0;
  268.  
  269.  for (loop=0;loop<loopsize;loop++)
  270.    {
  271.     int len;
  272.  
  273.     len=strlen(MenuStr[loop]);
  274.     if (len<maxw)
  275.       memset(&MenuStr[loop][len],' ',maxw-len);
  276.     strcat(MenuStr[loop],"\x5");
  277.  
  278.     sx=tempx;
  279.     sy=loop+1;
  280.     print(MenuStr[loop]);
  281.    }
  282.  
  283.   sx=tempx;
  284.   sy=loopsize+1;
  285.   print("\x6");
  286.   bar(sx,sy,sx+maxw-2,sy,7);
  287.   sx=tempx+maxw;
  288.   print("\x8");
  289.  
  290.  MouseShow();
  291.  OpenMenu=flag;
  292.  ItemOn=0;
  293. }
  294.  
  295.  
  296.  
  297. /////////////////////////////////////////////////////////////////
  298. //
  299. // Detect whether a menu is clicked on or not
  300. //
  301. /////////////////////////////////////////////////////////////////
  302. int DetectMenu(int x,int y)
  303. {
  304.  int flag,loop;
  305.  
  306.  if (y>10)
  307.    return 0;
  308.  
  309.  flag=0;
  310.  for (loop=0;loop<NumMenus;loop++)
  311.    if (x/8>=MenuInfo[loop].menux && x/8<MenuInfo[loop].menux+MenuInfo[loop].menunamelen)
  312.      {
  313.       flag=loop+1;
  314.       break;
  315.      }
  316.  return flag;
  317. }
  318.  
  319.  
  320.  
  321. /////////////////////////////////////////////////////////////////
  322. //
  323. // Highlight & De-highlight items
  324. //
  325. /////////////////////////////////////////////////////////////////
  326. void HandleHighlight(void (*UserRoutine)(void))
  327. {
  328.  int x,y,nitems,tempx,tempw,tempy,opmen;
  329.  
  330.  if (!OpenMenu)
  331.    {
  332.     UserRoutine();
  333.     return;
  334.    }
  335.  
  336.  MouseCoords(&x,&y);
  337.  nitems=(MBarPtr+OpenMenu-1)->num_items;
  338.  tempx=MenuInfo[OpenMenu-1].menux;
  339.  tempw=strlen(MenuStr[0])-5;
  340.  if (tempx+tempw+5>ScreenWidth)
  341.    tempx=ScreenWidth-tempw-5;
  342.  
  343.  opmen=DetectMenu(x,y);
  344.  if (opmen && opmen!=OpenMenu)
  345.    {
  346.     OpenMenu=0;
  347.     RestoreBackground();
  348.     HandleOpenMenu(UserRoutine,0);
  349.     return;
  350.    }
  351.  
  352.  //
  353.  // IS USER IN A MENU?
  354.  //
  355.  
  356.  if (x/8>tempx && x/8<tempx+tempw+4 && y>8 && y<(nitems+1)*8)
  357.    {
  358.     if (y/8==ItemOn)
  359.       return;    // EXIT IF ON SAME ITEM
  360.  
  361.     //
  362.     // IF AN ITEM IS CURRENTLY SELECTED, DEHIGHLIGHT IT
  363.     // AND HIGHLIGHT A NEW ITEM
  364.     //
  365.  
  366.     ChangeItem(y/8);
  367.    }
  368.  else
  369.    //
  370.    // USER MOVED POINTER OUTSIDE OF MENU; DEHIGHLIGHT ITEM
  371.    //
  372.  
  373.    if (ItemOn)
  374.      {
  375.       MouseHide();
  376.  
  377.       sx=tempx;
  378.       sy=ItemOn;
  379.       print(MenuStr[ItemOn-1]);
  380.  
  381.       ItemOn=0;
  382.       MouseShow();
  383.      }
  384. }
  385.  
  386.  
  387.  
  388. /////////////////////////////////////////////////////////////////
  389. //
  390. // Set new item highlighted
  391. //
  392. /////////////////////////////////////////////////////////////////
  393. void ChangeItem(int newitem)
  394. {
  395.  int tempx,tempw;
  396.  MenuDef *items;
  397.  char tempstr[80]="";
  398.  
  399.  tempx=MenuInfo[OpenMenu-1].menux;
  400.  if (tempx+strlen(MenuStr[0])>ScreenWidth)
  401.    tempx=ScreenWidth-strlen(MenuStr[0]);
  402.  
  403.  MouseHide();
  404.  if (ItemOn)
  405.    {
  406.     sx=tempx;
  407.     sy=ItemOn;
  408.     print(MenuStr[ItemOn-1]);
  409.    }
  410.  
  411.  xormask=0xffff;
  412.  ItemOn=newitem;
  413.  strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
  414.  sx=tempx+1;
  415.  sy=ItemOn;
  416.  print(tempstr);
  417.  xormask=0;
  418.  
  419.  MouseShow();
  420. }
  421.  
  422.  
  423.  
  424. /////////////////////////////////////////////////////////////////
  425. //
  426. // See if a menu was closed
  427. //
  428. /////////////////////////////////////////////////////////////////
  429. void HandleCloseMenu(void (*UserRoutine)(void))
  430. {
  431.  MenuDef *items;
  432.  int loop,tempx;
  433.  char tempstr[80]="";
  434.  
  435.  if (!OpenMenu)
  436.    {
  437.     UserRoutine();
  438.     return;
  439.    }
  440.  
  441.  if (ItemOn)
  442.    {
  443.     items=(MBarPtr+OpenMenu-1)->menu_def;
  444.     tempx=MenuInfo[OpenMenu-1].menux;
  445.     if (tempx+strlen(MenuStr[0])>ScreenWidth)
  446.       tempx=ScreenWidth-strlen(MenuStr[0]);
  447.  
  448.     for (loop=0;loop<NUMFLASHES;loop++)
  449.       {
  450.        xormask^=0xffff;
  451.        MouseHide();
  452.  
  453.        strncpy(tempstr,&MenuStr[ItemOn-1][1],strlen(MenuStr[ItemOn-1])-2);
  454.        sx=tempx+1;
  455.        sy=ItemOn;
  456.        print(tempstr);
  457.  
  458.        MouseShow();
  459.        WaitVBL(3);
  460.       }
  461.     xormask=0;
  462.     ItemRoutine=(items+ItemOn-1)->routine;
  463.    }
  464.  
  465.  OpenMenu=0;
  466.  RestoreBackground();
  467. }
  468.  
  469.  
  470. /////////////////////////////////////////////////////////////////
  471. //
  472. // Save the background
  473. //
  474. /////////////////////////////////////////////////////////////////
  475. void SaveBackground(int x,int y,int w,int h)
  476. {
  477.  long size;
  478.  unsigned loc,loop,loop1,seg,planelen;
  479.  
  480.  Back[WhichBack].savex=x;
  481.  Back[WhichBack].savey=y;
  482.  Back[WhichBack].savew=w;
  483.  Back[WhichBack].saveh=h;
  484.  
  485.  MouseHide();
  486.  switch (videomode)
  487.    {
  488.     case CGA:
  489.       MMAllocate(&Background[WhichBack],(w/4)*h);
  490.  
  491.       for(loop=y;loop<y+h;loop++)
  492.     {
  493.      loc=(loop/2)*80+0x2000*(loop&1)+x/4;
  494.      movedata(0xb800,loc,(unsigned)Background[WhichBack],(loop-y)*(w/4),w/4);
  495.     }
  496.       break;
  497.  
  498.     case EGA2:
  499.     case EGA1:
  500.       {
  501.        unsigned tempw=w/8,tempx=x/8,psize;
  502.  
  503.        planelen=tempw*h;
  504.        MMAllocate(&Background[WhichBack],5L*planelen);
  505.        outport(GCindex,GCmode);
  506.        for (loop=0;loop<4;loop++)
  507.      {
  508.       psize=loop*planelen;
  509.  
  510.       outport(GCindex,GCreadmap | loop*256);
  511.       for (loop1=y;loop1<y+h;loop1++)
  512.         movedata(0xa000,((unsigned)loop1*ScreenWidth)+tempx,
  513.           ((unsigned)Background[WhichBack])+(psize/16),
  514.           (psize&15)+((loop1-y)*tempw),tempw);
  515.      }
  516.       }
  517.       break;
  518.  
  519.     case VGA:
  520.       MMAllocate(&Background[WhichBack],(long)w*h);
  521.       for(loop=y;loop<y+h;loop++)
  522.     movedata(0xa000,loop*320+x,(unsigned)Background[WhichBack],(loop-y)*w,w);
  523.    }
  524.  MouseShow();
  525.  if (WhichBack<10)
  526.    WhichBack++;
  527. }
  528.  
  529.  
  530.  
  531. /////////////////////////////////////////////////////////////////
  532. //
  533. // Restore the background
  534. //
  535. /////////////////////////////////////////////////////////////////
  536. void setfarmem(char huge *mem,unsigned char val,unsigned len)
  537. {
  538.  int i;
  539.  for (i=0;i<len;i++)
  540.    *(mem+i)=val;
  541. }
  542.  
  543. void RestoreBackground(void)
  544. {
  545.  long size;
  546.  unsigned loc,loop1,x,y,w,h,loop,planelen;
  547.  
  548.  if (!Back[WhichBack-1].savex &&
  549.      !Back[WhichBack-1].savey &&
  550.      !Back[WhichBack-1].savew &&
  551.      !Back[WhichBack-1].saveh)
  552.    Quit("Can't RestoreBackground with no information!");
  553.  
  554.  x=Back[WhichBack-1].savex;
  555.  y=Back[WhichBack-1].savey;
  556.  w=Back[WhichBack-1].savew;
  557.  h=Back[WhichBack-1].saveh;
  558.  
  559.  MouseHide();
  560.  switch (videomode)
  561.    {
  562.     case CGA:
  563.       for(loop=y;loop<y+h;loop++)
  564.     {
  565.      loc=(loop/2)*80+0x2000*(loop&1)+x/4;
  566.      movedata((unsigned)Background[WhichBack-1],(loop-y)*(w/4),0xb800,loc,w/4);
  567.     }
  568.       break;
  569.  
  570.     case EGA2:
  571.     case EGA1:
  572.       planelen=(w/8)*h;
  573.       outport(GCindex,GCmode);
  574.       for (loop=0;loop<4;loop++)
  575.     {
  576.      outport(SCindex,SCmapmask | (1<<loop)*256);
  577.      for (loop1=y;loop1<y+h;loop1++)
  578.        movedata(((unsigned)Background[WhichBack-1])+((loop*planelen)/16),
  579.          ((loop*planelen)&15)+(loop1-y)*(w/8),
  580.          0xa000,loop1*ScreenWidth+x/8,w/8);
  581.     }
  582.       break;
  583.  
  584.     case VGA:
  585.       for(loop=y;loop<y+h;loop++)
  586.     movedata((unsigned)Background[WhichBack-1],(loop-y)*w,0xa000,loop*320+x,w);
  587.    }
  588.  
  589.  MMFreePtr(&Background[WhichBack-1]);
  590.  
  591.  MouseShow();
  592.  
  593.  WhichBack--;
  594.  Back[WhichBack].savex=0;
  595.  Back[WhichBack].savey=0;
  596.  Back[WhichBack].savew=0;
  597.  Back[WhichBack].saveh=0;
  598. }
  599.  
  600.  
  601. /////////////////////////////////////////////////////////////////
  602. //
  603. // Draw the Desktop
  604. //
  605. /////////////////////////////////////////////////////////////////
  606. void RedrawDesktop(void)
  607. {
  608.  int flag,count,i;
  609.  
  610.  ClearScreen();
  611.  
  612.  sx=sy=0;
  613.  bar(0,0,ScreenWidth-1,0,' ');
  614.  
  615.  flag=0;
  616.  count=0;
  617.  NumMenus=0;
  618.  while((MBarPtr+count)->num_items && !flag)
  619.    {
  620.     int len,max_width,loop;
  621.     MenuDef *the_item;
  622.     char string[80];
  623.  
  624.     //
  625.     // First, determine xcoord & namewidth & print
  626.     //
  627.  
  628.     strcpy(string,(MBarPtr+count)->menu_name);
  629.     len=strlen(string);
  630.     MenuInfo[NumMenus].menux=sx;
  631.     MenuInfo[NumMenus].menunamelen=len+2;
  632.     if (len+sx>ScreenWidth-1)
  633.       {
  634.        string[ScreenWidth-1-sx]=0;
  635.        MenuInfo[NumMenus].menunamelen=ScreenWidth-1-sx;
  636.        MenuInfo[NumMenus].menux=ScreenWidth-MenuInfo[NumMenus].menunamelen;
  637.        flag++;
  638.       }
  639.  
  640.     drawchar(sx++,sy,' ');
  641.     print(string);
  642.     drawchar(sx++,sy,' ');
  643.  
  644.     //
  645.     // Now, figure out length of widest item
  646.     //
  647.  
  648.     max_width=0;
  649.     the_item=(MBarPtr+count)->menu_def;
  650.  
  651.     for (loop=0;loop<(MBarPtr+count)->num_items;loop++)
  652.       {
  653.        int len;
  654.  
  655.        len=strlen((the_item+loop)->item_name);
  656.        if (len>max_width)
  657.      max_width=len;
  658.       }
  659.  
  660.     MenuInfo[NumMenus].menuwidth=max_width+1;
  661.  
  662.     count++;
  663.     NumMenus++;
  664.    }
  665.  
  666.  //
  667.  // clear bottom line of menubar
  668.  //
  669.  switch(videomode)
  670.  {
  671.   case CGA:
  672.     {
  673.      unsigned huge *CGAmem=MK_FP(0xb800,240+0x2000);
  674.      for(i=0;i<40;i++)
  675.        *(CGAmem+i)=0;
  676.     }
  677.     break;
  678.   case EGA1:
  679.   case EGA2:
  680.     {
  681.     char huge *EGAmem=MK_FP(0xa000,0);
  682.     outport(GCindex,GCmode);
  683.     outport(SCindex,0x0f00 | SCmapmask);
  684.     for (i=0;i<ScreenWidth;i++)
  685.       *(EGAmem+7*ScreenWidth+i)=0;
  686.     }
  687.     break;
  688.   case VGA:
  689.     {
  690.     unsigned huge *VGAmem=MK_FP(0xa000,320*7);
  691.     for (i=0;i<160;i++)
  692.       *(VGAmem+i)=0;
  693.     }
  694.  }
  695. }
  696.  
  697.  
  698.  
  699. /////////////////////////////////////////////////////////////////
  700. //
  701. // Init Desktop
  702. //
  703. /////////////////////////////////////////////////////////////////
  704. void InitDesktop(MBarDef *menubar,int initmouse)
  705. {
  706.  switch(videomode)
  707.    {
  708.     case CGA: ScreenWidth=40; break;
  709.     case EGA1: ScreenWidth=40; break;
  710.     case EGA2: ScreenWidth=80; break;
  711.     case VGA: ScreenWidth=40;
  712.    }
  713.  
  714.  MBarPtr=menubar;
  715.  RedrawDesktop();
  716.  if (initmouse)
  717.    MouseInit();
  718.  OpenMenu=KeybdOn=0;
  719.  if (!MouseStatus)
  720.    KeybdOn=1;
  721. }
  722.  
  723.  
  724.  
  725.  
  726. ////////////////////////////////////////////////////////////////////
  727. //
  728. // Clear the current screen
  729. //
  730. ////////////////////////////////////////////////////////////////////
  731. void ClearScreen(void)
  732. {
  733.  unsigned size,segment;
  734.  
  735.  segment=0xa000;
  736.  switch(videomode)
  737.    {
  738.     case CGA: segment=0xb800; size=CGASIZE/2; break;
  739.     case EGA1: size=EGA1SIZE/2; break;
  740.     case EGA2: size=EGA2SIZE/2; break;
  741.     case VGA: size=VGASIZE/2;
  742.    }
  743.  
  744.  MouseHide();
  745.  
  746.  asm    push    di
  747.  asm    push    es
  748.  asm    xor    di,di
  749.  asm    mov    ax,segment
  750.  asm    mov    es,ax
  751.  asm    mov    cx,size
  752.  asm    cld
  753.  asm    xor    ax,ax
  754.  asm    rep stosw
  755.  asm    pop    es
  756.  asm    pop    di
  757.  
  758.  MouseShow();
  759. }
  760.  
  761.  
  762.  
  763. /////////////////////////////////////////////////////////
  764. //
  765. // print a representation of the scan code key
  766. //
  767. /////////////////////////////////////////////////////////
  768. char *PassScancode(int sc)
  769. {
  770.  char smallstr[2];
  771.  char static chartable[128] =
  772.  {' ',' ','1','2','3','4','5','6','7','8','9','0','-','+','?','?',
  773.   'Q','W','E','R','T','Y','U','I','O','P','[',']','|','?','A','S',
  774.   'D','F','G','H','J','K','L',';','"',' ',' ',' ','Z','X','C','V',
  775.   'B','N','M',',','.','/','?',' ',' ',' ',' ',' ',' ',' ',' ',' ',
  776.   ' ',' ',' ',' ',' ',' ',' ',' ', 15,' ','-', 14,'5', 31,'+',' ',
  777.    19,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
  778.   ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
  779.   ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
  780.  
  781.  sc = sc & 0x7f;
  782.  
  783.  if (sc==1)
  784.    strcpy(tempstr,"ESC");
  785.  else if (sc==0x48)
  786.    strcpy(tempstr,"\xb");
  787.  else if (sc==0x50)
  788.    strcpy(tempstr,"\xc");
  789.  else if (sc==0xe)
  790.    strcpy(tempstr,"BKSP");
  791.  else if (sc==0xf)
  792.    strcpy(tempstr,"TAB");
  793.  else if (sc==0x1d)
  794.    strcpy(tempstr,"CTRL");
  795.  else if (sc==0x2A)
  796.    strcpy(tempstr,"LSHIFT");
  797.  else if (sc==0x39)
  798.    strcpy(tempstr,"SPACE");
  799.  else if (sc==0x3A)
  800.    strcpy(tempstr,"CAPSLK");
  801.  else if (sc>=0x3b && sc<=0x44)
  802.  {
  803.    char str[3];
  804.    strcpy(tempstr,"F");
  805.    itoa (sc-0x3a,str,10);
  806.    strcat(tempstr,str);
  807.  }
  808.  else if (sc==0x57)
  809.    strcpy(tempstr,"F11");
  810.  else if (sc==0x59)
  811.    strcpy(tempstr,"F12");
  812.  else if (sc==0x46)
  813.    strcpy(tempstr,"SCRLLK");
  814.  else if (sc==0x1c)
  815.    strcpy(tempstr,"ENTER");
  816.  else if (sc==0x36)
  817.    strcpy(tempstr,"RSHIFT");
  818.  else if (sc==0x37)
  819.    strcpy(tempstr,"PRTSC");
  820.  else if (sc==0x38)
  821.    strcpy(tempstr,"ALT");
  822.  else if (sc==0x47)
  823.    strcpy(tempstr,"HOME");
  824.  else if (sc==0x49)
  825.    strcpy(tempstr,"PGUP");
  826.  else if (sc==0x4f)
  827.    strcpy(tempstr,"END");
  828.  else if (sc==0x51)
  829.    strcpy(tempstr,"PGDN");
  830.  else if (sc==0x52)
  831.    strcpy(tempstr,"INS");
  832.  else if (sc==0x53)
  833.    strcpy(tempstr,"DEL");
  834.  else if (sc==0x45)
  835.    strcpy(tempstr,"NUMLK");
  836.  else
  837.    {
  838.     smallstr[0]=chartable[sc];
  839.     smallstr[1]=0;
  840.     strcpy(tempstr,smallstr);
  841.    }
  842.  
  843.  return tempstr;
  844. }
  845.  
  846. /////////////////////////////////////////////////////////
  847. /////////////////////////////////////////////////////////
  848. /////////////////////////////////////////////////////////
  849. //
  850. //
  851. // DIALOG MANAGER CODE
  852. //
  853. //
  854. /////////////////////////////////////////////////////////
  855. /////////////////////////////////////////////////////////
  856. /////////////////////////////////////////////////////////
  857.  
  858. /////////////////////////////////////////////////////////
  859. //
  860. // Dialog Boxes!
  861. //
  862. /////////////////////////////////////////////////////////
  863. int DoDialog(DialogDef *TheDialog)
  864. {
  865.  btype *TheButton;
  866.  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
  867.  
  868.  for (i=0;i<30;i++)
  869.    xc[i]=yc[i]=wid[i]=0;
  870.  
  871.  MouseHide();
  872.  SaveBackground((screencenterx-TheDialog->width/2)*8,
  873.    (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
  874.    (TheDialog->height+2)*8);
  875.  
  876.  xormask=0;
  877.  centerwindow(TheDialog->width,TheDialog->height);
  878.  ox=sx;
  879.  oy=sy;
  880.  print(TheDialog->text);
  881.  for (i=0;i<TheDialog->numbuttons;i++)
  882.    {
  883.     int xx,yy,j;
  884.  
  885.     TheButton=TheDialog->buttons;
  886.  
  887.     xc[i]=sx=ox+(TheButton+i)->xoff;
  888.     yc[i]=sy=oy+(TheButton+i)->yoff;
  889.     xx=sx-1;
  890.     yy=sy-1;
  891.     print((TheButton+i)->text);
  892.     wid[i]=strlen((TheButton+i)->text);
  893.  
  894.     if ((TheButton+i)->border)
  895.       DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
  896.    }
  897.  
  898.  if (TheDialog->hook)
  899.    {
  900.     HookRoutine=(void (*)(int x,int y))TheDialog->hook;
  901.     HookRoutine(ox,oy);
  902.    }
  903.  MouseShow();
  904.  
  905.  clearkeys();
  906.  do
  907.  {
  908.   char temp;
  909.   int mx,my;
  910.  
  911.   temp=((temp<<1)|(MouseButton()&1))&3;
  912.   MouseCoords(&mx,&my);
  913.   mx/=8;
  914.   my/=8;
  915.  
  916.   //
  917.   // ENTER press
  918.   //
  919.   if (keydown[0x1c])
  920.     for(i=0;i<TheDialog->numbuttons;i++)
  921.       {
  922.        TheButton=TheDialog->buttons;
  923.        if ((TheButton+i)->border==2)
  924.      {
  925.       Clicked=i+1;
  926.       Released=1;
  927.       temp=Float=0;
  928.       while(keydown[0x1c]);
  929.       clearkeys();
  930.      }
  931.       }
  932.  
  933.   //
  934.   // ESC press
  935.   //
  936.   if (keydown[1])
  937.     {
  938.      temp=Float=Clicked=0;
  939.      Released=1;
  940.      while(keydown[1]);
  941.     }
  942.  
  943.   switch(temp)
  944.   {
  945.    case 0: // upup (no press)
  946.      break;
  947.    case 3: // downdown (held down)
  948.      if (!Float && Clicked && (mx<xc[Clicked-1] ||
  949.      mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
  950.        {
  951.     xormask=0;
  952.     sx=xc[Clicked-1];
  953.     sy=yc[Clicked-1];
  954.     MouseHide();
  955.     print((TheButton+Clicked-1)->text);
  956.     MouseShow();
  957.     xormask=1;
  958.     Float=1;
  959.        }
  960.      else
  961.      if (Float && mx>=xc[Clicked-1] &&
  962.      mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
  963.        {
  964.     xormask=1;
  965.     sx=xc[Clicked-1];
  966.     sy=yc[Clicked-1];
  967.     MouseHide();
  968.     print((TheButton+Clicked-1)->text);
  969.     MouseShow();
  970.     xormask=0;
  971.     Float=0;
  972.        }
  973.      break;
  974.    case 1: // updown (press)
  975.      for (i=0;i<TheDialog->numbuttons;i++)
  976.        {
  977.     if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
  978.       {
  979.        Clicked=i+1;
  980.        xormask=1;
  981.        sx=xc[i];
  982.        sy=yc[i];
  983.        MouseHide();
  984.        print((TheButton+i)->text);
  985.        MouseShow();
  986.        xormask=0;
  987.        break;
  988.       }
  989.        }
  990.      break;
  991.    case 2: // downup (release)
  992.      if (Clicked && !Float)
  993.        Released++;
  994.   }
  995.  } while (!Released);
  996.  
  997.  RestoreBackground();
  998.  return Clicked;
  999. }
  1000.  
  1001.  
  1002. /////////////////////////////////////////////////////////
  1003. //
  1004. // Just CHECK a Dialog Box's BUTTONS
  1005. //
  1006. /////////////////////////////////////////////////////////
  1007. int CheckButtons(DialogDef *TheDialog)
  1008. {
  1009.  btype *TheButton;
  1010.  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
  1011.  
  1012.  for (i=0;i<30;i++)
  1013.    xc[i]=yc[i]=wid[i]=0;
  1014.  
  1015.  ox=screencenterx-TheDialog->width/2+1;
  1016.  oy=screencentery-TheDialog->height/2+1;
  1017.  for (i=0;i<TheDialog->numbuttons;i++)
  1018.    {
  1019.     int xx,yy,j;
  1020.  
  1021.     TheButton=TheDialog->buttons;
  1022.  
  1023.     xc[i]=ox+(TheButton+i)->xoff;
  1024.     yc[i]=oy+(TheButton+i)->yoff;
  1025.     wid[i]=strlen((TheButton+i)->text);
  1026.    }
  1027.  
  1028.  
  1029.  clearkeys();
  1030.  do
  1031.  {
  1032.   char temp;
  1033.   int mx,my;
  1034.  
  1035.   temp=((temp<<1)|(MouseButton()&1))&3;
  1036.   MouseCoords(&mx,&my);
  1037.   mx/=8;
  1038.   my/=8;
  1039.  
  1040.   //
  1041.   // ENTER press
  1042.   //
  1043.   if (keydown[0x1c])
  1044.     for(i=0;i<TheDialog->numbuttons;i++)
  1045.       {
  1046.        TheButton=TheDialog->buttons;
  1047.        if ((TheButton+i)->border==2)
  1048.      {
  1049.       Clicked=i+1;
  1050.       Released=1;
  1051.       temp=Float=0;
  1052.       while(keydown[0x1c]);
  1053.       clearkeys();
  1054.      }
  1055.       }
  1056.  
  1057.   //
  1058.   // ESC press
  1059.   //
  1060.   if (keydown[1])
  1061.     {
  1062.      temp=Float=Clicked=0;
  1063.      Released=1;
  1064.      while(keydown[1]);
  1065.     }
  1066.  
  1067.   switch(temp)
  1068.   {
  1069.    case 0: // upup (no press)
  1070.      break;
  1071.    case 3: // downdown (held down)
  1072.      if (!Float && Clicked && (mx<xc[Clicked-1] ||
  1073.      mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
  1074.        {
  1075.     xormask=0;
  1076.     sx=xc[Clicked-1];
  1077.     sy=yc[Clicked-1];
  1078.     MouseHide();
  1079.     print((TheButton+Clicked-1)->text);
  1080.     MouseShow();
  1081.     xormask=1;
  1082.     Float=1;
  1083.        }
  1084.      else
  1085.      if (Float && mx>=xc[Clicked-1] &&
  1086.      mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
  1087.        {
  1088.     xormask=1;
  1089.     sx=xc[Clicked-1];
  1090.     sy=yc[Clicked-1];
  1091.     MouseHide();
  1092.     print((TheButton+Clicked-1)->text);
  1093.     MouseShow();
  1094.     xormask=0;
  1095.     Float=0;
  1096.        }
  1097.      break;
  1098.    case 1: // updown (press)
  1099.      for (i=0;i<TheDialog->numbuttons;i++)
  1100.        {
  1101.     if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
  1102.       {
  1103.        Clicked=i+1;
  1104.        xormask=1;
  1105.        sx=xc[i];
  1106.        sy=yc[i];
  1107.        MouseHide();
  1108.        print((TheButton+i)->text);
  1109.        MouseShow();
  1110.        xormask=0;
  1111.        break;
  1112.       }
  1113.        }
  1114.      break;
  1115.    case 2: // downup (release)
  1116.      if (Clicked && !Float)
  1117.        Released++;
  1118.   }
  1119.  } while (!Released);
  1120.  clearkeys();
  1121.  
  1122.  if (Clicked)
  1123.  {
  1124.   sx=xc[Clicked-1];
  1125.   sy=yc[Clicked-1];
  1126.   MouseHide();
  1127.   print((TheButton+Clicked-1)->text);
  1128.   MouseShow();
  1129.  }
  1130.  
  1131.  return Clicked;
  1132. }
  1133.  
  1134.  
  1135. /////////////////////////////////////////////////////////
  1136. //
  1137. // Just CHECK a Dialog Box's BUTTONS
  1138. // BUT!...RETURN IF MOUSE BUTTON IS PRESSED OUTSIDE DIALOG BUTTON!
  1139. //
  1140. /////////////////////////////////////////////////////////
  1141. int CheckButtonsRet(DialogDef *TheDialog)
  1142. {
  1143.  btype *TheButton;
  1144.  int i,ox,oy,Float=0,Released=0,Clicked=0,xc[30],yc[30],wid[30];
  1145.  
  1146.  for (i=0;i<30;i++)
  1147.    xc[i]=yc[i]=wid[i]=0;
  1148.  
  1149.  ox=screencenterx-TheDialog->width/2+1;
  1150.  oy=screencentery-TheDialog->height/2+1;
  1151.  for (i=0;i<TheDialog->numbuttons;i++)
  1152.    {
  1153.     int xx,yy,j;
  1154.  
  1155.     TheButton=TheDialog->buttons;
  1156.  
  1157.     xc[i]=ox+(TheButton+i)->xoff;
  1158.     yc[i]=oy+(TheButton+i)->yoff;
  1159.     wid[i]=strlen((TheButton+i)->text);
  1160.    }
  1161.  
  1162.  do
  1163.  {
  1164.   char temp;
  1165.   int mx,my;
  1166.  
  1167.   temp=((temp<<1)|(MouseButton()&1))&3;
  1168.   if (MouseButton()&2)
  1169.     return -1;
  1170.  
  1171.   MouseCoords(&mx,&my);
  1172.   mx/=8;
  1173.   my/=8;
  1174.  
  1175.   //
  1176.   // ENTER press
  1177.   //
  1178.   if (keydown[0x1c])
  1179.     for(i=0;i<TheDialog->numbuttons;i++)
  1180.       {
  1181.        TheButton=TheDialog->buttons;
  1182.        if ((TheButton+i)->border==2)
  1183.      {
  1184.       Clicked=i+1;
  1185.       Released=1;
  1186.       temp=Float=0;
  1187.       while(keydown[0x1c]);
  1188.       clearkeys();
  1189.      }
  1190.       }
  1191.  
  1192.   //
  1193.   // ESC press
  1194.   //
  1195.   if (keydown[1])
  1196.     {
  1197.      temp=Float=Clicked=0;
  1198.      Released=1;
  1199.      while(keydown[1]);
  1200.     }
  1201.  
  1202.   //
  1203.   // arrows or PgUp/PgDn/Home/End
  1204.   //
  1205.   if (keydown[0x48] || keydown[0x50] || keydown[0x4b] || keydown[0x4d] ||
  1206.       keydown[0x49] || keydown[0x51] || keydown[0x47] || keydown[0x4f] ||
  1207.       keydown[0x39] || keydown[0x2e])
  1208.     return -1;
  1209.  
  1210.   switch(temp)
  1211.   {
  1212.    case 0: // upup (no press)
  1213.      break;
  1214.    case 3: // downdown (held down)
  1215.      if (!Float && Clicked && (mx<xc[Clicked-1] ||
  1216.      mx>xc[Clicked-1]+wid[Clicked-1]-1 || my!=yc[Clicked-1]))
  1217.        {
  1218.     xormask=0;
  1219.     sx=xc[Clicked-1];
  1220.     sy=yc[Clicked-1];
  1221.     MouseHide();
  1222.     print((TheButton+Clicked-1)->text);
  1223.     MouseShow();
  1224.     xormask=1;
  1225.     Float=1;
  1226.        }
  1227.      else
  1228.      if (Float && mx>=xc[Clicked-1] &&
  1229.      mx<xc[Clicked-1]+wid[Clicked-1] && my==yc[Clicked-1])
  1230.        {
  1231.     xormask=1;
  1232.     sx=xc[Clicked-1];
  1233.     sy=yc[Clicked-1];
  1234.     MouseHide();
  1235.     print((TheButton+Clicked-1)->text);
  1236.     MouseShow();
  1237.     xormask=0;
  1238.     Float=0;
  1239.        }
  1240.      break;
  1241.    case 1: // updown (press)
  1242.      for (i=0;i<TheDialog->numbuttons;i++)
  1243.        {
  1244.     if (mx>=xc[i] && mx<xc[i]+wid[i] && my==yc[i])
  1245.       {
  1246.        Clicked=i+1;
  1247.        xormask=1;
  1248.        sx=xc[i];
  1249.        sy=yc[i];
  1250.        MouseHide();
  1251.        print((TheButton+i)->text);
  1252.        MouseShow();
  1253.        xormask=0;
  1254.        break;
  1255.       }
  1256.        }
  1257.  
  1258.      if (!Clicked)    // MOD TO ORIGINAL CHECKBUTTONS
  1259.        return -1;
  1260.  
  1261.      break;
  1262.    case 2: // downup (release)
  1263.      if (Clicked && !Float)
  1264.        Released++;
  1265.   }
  1266.  } while (!Released);
  1267.  clearkeys();
  1268.  return Clicked;
  1269. }
  1270.  
  1271.  
  1272. /////////////////////////////////////////////////////////
  1273. //
  1274. // Just DRAW a Dialog Box
  1275. //
  1276. /////////////////////////////////////////////////////////
  1277. void DrawDialog(DialogDef *TheDialog,int saveback)
  1278. {
  1279.  btype *TheButton;
  1280.  int i,ox,oy,xc[30],yc[30],wid[30];
  1281.  
  1282.  for (i=0;i<30;i++)
  1283.    xc[i]=yc[i]=wid[i]=0;
  1284.  
  1285.  MouseHide();
  1286.  if (saveback)
  1287.    SaveBackground((screencenterx-TheDialog->width/2)*8,
  1288.      (screencentery-TheDialog->height/2)*8,(TheDialog->width+2)*8,
  1289.      (TheDialog->height+2)*8);
  1290.  
  1291.  xormask=0;
  1292.  centerwindow(TheDialog->width,TheDialog->height);
  1293.  ox=sx;
  1294.  oy=sy;
  1295.  print(TheDialog->text);
  1296.  for (i=0;i<TheDialog->numbuttons;i++)
  1297.    {
  1298.     int xx,yy,j;
  1299.  
  1300.     TheButton=TheDialog->buttons;
  1301.  
  1302.     xc[i]=sx=ox+(TheButton+i)->xoff;
  1303.     yc[i]=sy=oy+(TheButton+i)->yoff;
  1304.     xx=sx-1;
  1305.     yy=sy-1;
  1306.     print((TheButton+i)->text);
  1307.     wid[i]=strlen((TheButton+i)->text);
  1308.  
  1309.     if ((TheButton+i)->border)
  1310.       DrawBorder(xx,yy,wid[i]+1,2,(TheButton+i)->border);
  1311.    }
  1312.  
  1313.  if (TheDialog->hook)
  1314.    {
  1315.     HookRoutine=(void (*)(int x,int y))TheDialog->hook;
  1316.     HookRoutine(ox,oy);
  1317.    }
  1318.  
  1319.  MouseShow();
  1320. }
  1321.  
  1322.  
  1323. /////////////////////////////////////////////////////////
  1324. //
  1325. // Error Dialog Box
  1326. //
  1327. /////////////////////////////////////////////////////////
  1328. char errstring[200],bstring[20];
  1329. btype ERROKb={bstring,0,0,2};
  1330. DialogDef ERRR={errstring,0,0,1,&ERROKb,NULL};
  1331.  
  1332. void ErrDialog(char *string,char *bstr)
  1333. {
  1334.  int maxw=0,width=0,height=1,i;
  1335.  
  1336.  if (strlen(string)>200)
  1337.    Quit("Programmer Error: ErrDialog string is too long!");
  1338.  
  1339.  for (i=0;i<strlen(string);i++)
  1340.    {
  1341.     width++;
  1342.     if (width>maxw)
  1343.       maxw=width;
  1344.  
  1345.     if (string[i]=='\n')
  1346.       {
  1347.        height++;
  1348.        width=0;
  1349.       }
  1350.    }
  1351.  height+=3;    // add for button!
  1352.  
  1353.  if (strlen(bstr)>maxw)
  1354.    Quit("Programmer Error: ErrDialog BUTTONstring is longer than dialog!");
  1355.  
  1356.  strcpy(bstring,bstr);
  1357.  strcpy(errstring,string);
  1358.  ERRR.width=maxw;
  1359.  ERRR.height=height;
  1360.  ERRR.numbuttons=1;
  1361.  if (!bstr[0])
  1362.    {
  1363.     ERRR.numbuttons=0;
  1364.     ERRR.height-=3;
  1365.    }
  1366.  
  1367.  ERROKb.xoff=(maxw/2)-(strlen(bstr)/2);
  1368.  ERROKb.yoff=height-2;
  1369.  
  1370.  if (bstr[0])
  1371.    DoDialog(&ERRR);
  1372.  else
  1373.    DrawDialog(&ERRR,1);
  1374. }
  1375.  
  1376.  
  1377. /////////////////////////////////////////////////////////
  1378. //
  1379. // Draw a border
  1380. //
  1381. /////////////////////////////////////////////////////////
  1382. void DrawBorder(int x,int y,int w,int h,int b)
  1383. {
  1384.  int xx=x,yy=y,j;
  1385.  
  1386.  if (b==2)
  1387.    {
  1388.     drawchar(xx,yy,15);
  1389.     drawchar(xx+w,yy,17);
  1390.     drawchar(xx,yy+h,20);
  1391.     drawchar(xx+w,yy+h,22);
  1392.  
  1393.     for (j=yy+1;j<yy+h;j++)
  1394.       {
  1395.        drawchar(xx,j,18);
  1396.        drawchar(xx+w,j,19);
  1397.       }
  1398.     for (j=xx+1;j<xx+w;j++)
  1399.       {
  1400.        drawchar(j,yy,16);
  1401.        drawchar(j,yy+h,21);
  1402.       }
  1403.    }
  1404.  
  1405.  if (b==1)
  1406.    {
  1407.     drawchar(xx,yy,23);
  1408.     drawchar(xx+w,yy,25);
  1409.     drawchar(xx,yy+h,28);
  1410.     drawchar(xx+w,yy+h,30);
  1411.  
  1412.     for (j=yy+1;j<yy+h;j++)
  1413.       {
  1414.        drawchar(xx,j,26);
  1415.        drawchar(xx+w,j,27);
  1416.       }
  1417.     for (j=xx+1;j<xx+w;j++)
  1418.       {
  1419.        drawchar(j,yy,24);
  1420.        drawchar(j,yy+h,29);
  1421.       }
  1422.    }
  1423.  
  1424. }
  1425.  
  1426.  
  1427. /////////////////////////////////////////////////////////
  1428. //
  1429. // Get the XY coords of a dialog's button
  1430. //
  1431. /////////////////////////////////////////////////////////
  1432. void GetButtonXY(DialogDef *TheDialog,int button,unsigned *x,unsigned *y)
  1433. {
  1434.  btype *TheButton;
  1435.  
  1436.  TheButton=TheDialog->buttons;
  1437.  
  1438.  *x=(TheButton+button)->xoff+screencenterx-TheDialog->width/2+1;
  1439.  *y=(TheButton+button)->yoff+screencentery-TheDialog->height/2+1;
  1440. }
  1441.  
  1442.  
  1443. /////////////////////////////////////////////////////////
  1444. //
  1445. // Get the XY coords of a dialog
  1446. //
  1447. /////////////////////////////////////////////////////////
  1448. void GetDialogXY(DialogDef *TheDialog,unsigned *x,unsigned *y)
  1449. {
  1450.  *x=screencenterx-TheDialog->width/2+1;
  1451.  *y=screencentery-TheDialog->height/2+1;
  1452. }
  1453.  
  1454.  
  1455. ////////////////////////////////////////////////////
  1456. //
  1457. // Allow user to select a list item (like the menus)
  1458. //
  1459. ////////////////////////////////////////////////////
  1460. int CheckList(int x,int y,int w,int h,void (*oncode)(),void (*offcode)(),int blink)
  1461. {
  1462.  enum {upup,updown,downup,downdown} clicks;
  1463.  static char bpress=0;
  1464.  unsigned mx,my,i;
  1465.  int high=-1;
  1466.  
  1467.  
  1468.  while(1)
  1469.  {
  1470.   MouseCoords(&(int)mx,&(int)my);
  1471.   mx/=8;
  1472.   my/=8;
  1473.   bpress=((bpress<<1)|(MouseButton()&1))&3;
  1474.   switch(bpress)
  1475.   {
  1476.    case upup:
  1477.      return -1;
  1478.    case updown:
  1479.      if (mx>=x && mx<x+w && my>=y && my<y+h)
  1480.        {
  1481.     high=my-y;
  1482.     MouseHide();
  1483.     oncode(x,my,high);
  1484.     MouseShow();
  1485.        }
  1486.      else
  1487.        return -1;
  1488.  
  1489.      break;
  1490.    case downup:
  1491.      if (high!=-1)
  1492.        {
  1493.     if (blink)
  1494.       for(i=0;i<5;i++)
  1495.       {
  1496.        MouseHide();
  1497.        oncode(x,my,high);
  1498.        MouseShow();
  1499.        WaitVBL(3);
  1500.  
  1501.        MouseHide();
  1502.        offcode(x,my,high);
  1503.        WaitVBL(3);
  1504.        MouseShow();
  1505.       }
  1506.        }
  1507.      return high;
  1508.  
  1509.    case downdown:
  1510.      if (mx>=x && mx<x+w && my>=y && my<y+h)
  1511.        {
  1512.     if (my-y != high && high!=-1)
  1513.       {
  1514.        MouseHide();
  1515.        offcode(x,high+y,high);
  1516.        MouseShow();
  1517.  
  1518.       }
  1519.  
  1520.     if (my-y != high)
  1521.       {
  1522.        high=my-y;
  1523.        MouseHide();
  1524.        oncode(x,y+high,high);
  1525.        MouseShow();
  1526.       }
  1527.        }
  1528.      else
  1529.        {
  1530.     if (high!=-1)
  1531.       {
  1532.        MouseHide();
  1533.        offcode(x,high+y,high);
  1534.        MouseShow();
  1535.       }
  1536.     high=-1;
  1537.     return -1;
  1538.        }
  1539.   }
  1540.  }
  1541. }
  1542.  
  1543.  
  1544. /////////////////////////////////////////////////
  1545. //
  1546. // Message dialog
  1547. // Returns: -1=ESC, 0=No, 1=Yes
  1548. //
  1549. /////////////////////////////////////////////////
  1550. char MessStr[200];
  1551. btype MessOKb[]={{" No ",0,0,1},{" Yes ",0,0,2}};
  1552. DialogDef Mess={MessStr,0,0,2,&MessOKb[0],NULL};
  1553.  
  1554. int Message(char *string)
  1555. {
  1556.  int maxw=0,width=0,height=1,i;
  1557.  
  1558.  if (strlen(string)>200)
  1559.    Quit("Programmer Error: Message string is too long!");
  1560.  
  1561.  for (i=0;i<strlen(string);i++)
  1562.    {
  1563.     width++;
  1564.     if (width>maxw)
  1565.       maxw=width;
  1566.  
  1567.     if (string[i]=='\n')
  1568.       {
  1569.        height++;
  1570.        width=0;
  1571.       }
  1572.    }
  1573.  height+=3;    // add for buttons!
  1574.  
  1575.  strcpy(MessStr,string);
  1576.  Mess.width=maxw;
  1577.  Mess.height=height;
  1578.  
  1579.  MessOKb[1].xoff=(maxw/4)-(strlen(MessOKb[0].text)/2);
  1580.  MessOKb[1].yoff=height-2;
  1581.  MessOKb[0].xoff=(maxw/4)*3-(strlen(MessOKb[1].text)/2);
  1582.  MessOKb[0].yoff=height-2;
  1583.  
  1584.  return DoDialog(&Mess);
  1585. }
  1586.  
  1587.  
  1588. /////////////////////////////////////////////////
  1589. //
  1590. // GetPath dialog
  1591. // *path is returned
  1592. // (exit:0 if OK,-1 if Not Successful,-2 if Canceled)
  1593. //
  1594. /////////////////////////////////////////////////
  1595. #define LISTX    1
  1596. #define LISTY    3
  1597.  
  1598. char dstr[80];
  1599. btype GPb={"Cancel",15,3,1};
  1600. DialogDef GPd={dstr,22,14,1,&GPb,NULL};
  1601. char NameList[MAXFDNAMES][13];
  1602. int base;
  1603. struct ffblk f;
  1604.  
  1605. int GetPath(char *string,char *filter,char *path)
  1606. {
  1607.  char pname[64];
  1608.  unsigned int numnames=0,max,dx,dy,redraw,exit;
  1609.  int select,zset,i;
  1610.  
  1611.  
  1612.  strcpy(pname,filter);
  1613.  for (zset=0,i=strlen(pname);i>=0;i--)
  1614.    if (pname[i]=='\\')
  1615.      {
  1616.       pname[i+1]=0;
  1617.       zset++;
  1618.       break;
  1619.      }
  1620.  if (!zset)
  1621.    pname[0]=0;
  1622.  
  1623.  strcpy(dstr,string);
  1624.  //
  1625.  // FIRST, GET THE NAMES FROM THE DIRECTORY
  1626.  //
  1627.  if (findfirst(filter,&f,FA_ARCH))
  1628.    return -1;
  1629.  strcpy(NameList[numnames++],f.ff_name);
  1630.  
  1631.  while(!findnext(&f) && numnames<MAXFDNAMES)
  1632.    strcpy(NameList[numnames++],f.ff_name);
  1633.  
  1634.  DrawDialog(&GPd,1);
  1635.  MouseHide();
  1636.  GetDialogXY(&GPd,&dx,&dy);
  1637.  DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
  1638.  MouseShow();
  1639.  
  1640.  base=exit=0;
  1641.  
  1642.  //
  1643.  // THIS LOOP DRAWS THE DIALOG
  1644.  //
  1645.  do
  1646.  {
  1647.   redraw=0;
  1648.   MouseHide();
  1649.   max=10;
  1650.   if (numnames<10)
  1651.     max=numnames;
  1652.   for (i=0;i<max;i++)
  1653.     {
  1654.      bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
  1655.      FDoff(dx+LISTX,dy+LISTY+i,i);
  1656.     }
  1657.   MouseShow();
  1658.  
  1659.   //
  1660.   // THIS LOOP CHECKS INPUT
  1661.   //
  1662.   do
  1663.   {
  1664.    select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
  1665.    if (select>=0)
  1666.      {
  1667.       redraw=exit=1;
  1668.       continue;
  1669.      }
  1670.  
  1671.    GetButtonXY(&GPd,0,&sx,&sy);
  1672.    select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
  1673.    if (!select || keydown[1])
  1674.      {
  1675.       RestoreBackground();
  1676.       while(keydown[1]);
  1677.       clearkeys();
  1678.       return -2;
  1679.      }
  1680.  
  1681.    //
  1682.    // CHECK ARROWS & PGUP/DN
  1683.    //
  1684.    if (keydown[0x48] && base)
  1685.      {
  1686.       base--;
  1687.       redraw=1;
  1688.       if (!keydown[0x1d])
  1689.     while(keydown[0x48]);
  1690.      }
  1691.    else
  1692.    if (keydown[0x50] && base+10<numnames)
  1693.      {
  1694.       base++;
  1695.       redraw=1;
  1696.       if (!keydown[0x1d])
  1697.     while(keydown[0x50]);
  1698.      }
  1699.    else
  1700.    if (keydown[0x49])
  1701.      {
  1702.       base-=10;
  1703.       if (base<0)
  1704.     base=0;
  1705.       redraw=1;
  1706.       if (!keydown[0x1d])
  1707.     while(keydown[0x49]);
  1708.      }
  1709.    else
  1710.    if (keydown[0x51])
  1711.      {
  1712.       base+=10;
  1713.       if (base+10>numnames)
  1714.     base=numnames-10;
  1715.       redraw=1;
  1716.       if (!keydown[0x1d])
  1717.     while(keydown[0x51]);
  1718.      }
  1719.  
  1720.   } while(!redraw);
  1721.  } while(!exit);
  1722.  
  1723.  //
  1724.  // RETURN PATHNAME
  1725.  //
  1726.  RestoreBackground();
  1727.  strcpy(path,pname);
  1728.  strcat(path,NameList[select+base]);
  1729.  findfirst(path,&f,FA_ARCH);
  1730.  return 0;
  1731. }
  1732.  
  1733.  
  1734. static void FDon(int x,int y,int w)
  1735. {
  1736.  xormask=1;
  1737.  FDoff(x,y,w);
  1738.  xormask=0;
  1739. }
  1740.  
  1741. static void FDoff(int x,int y,int w)
  1742. {
  1743.  MouseHide();
  1744.  sx=x;
  1745.  sy=y;
  1746.  print(NameList[w+base]);
  1747.  MouseShow();
  1748. }
  1749.  
  1750.  
  1751. static void CancelOn(int x,int y)
  1752. {
  1753.  xormask=1;
  1754.  CancelOff(x,y);
  1755.  xormask=0;
  1756. }
  1757.  
  1758. static void CancelOff(int x,int y)
  1759. {
  1760.  MouseHide();
  1761.  sx=x;
  1762.  sy=y;
  1763.  print("Cancel");
  1764.  MouseShow();
  1765. }
  1766.  
  1767.  
  1768. /////////////////////////////////////////////////
  1769. //
  1770. // GetList dialog
  1771. // Fill "NameList[?][13]" with your strings
  1772. // (exit:>=0 is selection,-1 if Not Successful,-2 if Canceled)
  1773. //
  1774. /////////////////////////////////////////////////
  1775. int GetList(char *string,int numnames)
  1776. {
  1777.  unsigned int max,dx,dy,redraw,exit,i;
  1778.  int select;
  1779.  
  1780.  
  1781.  strcpy(dstr,string);
  1782.  
  1783.  DrawDialog(&GPd,1);
  1784.  MouseHide();
  1785.  GetDialogXY(&GPd,&dx,&dy);
  1786.  DrawBorder(dx+LISTX-1,dy+LISTY-1,13,11,1);
  1787.  MouseShow();
  1788.  
  1789.  base=exit=0;
  1790.  
  1791.  //
  1792.  // THIS LOOP DRAWS THE DIALOG
  1793.  //
  1794.  do
  1795.  {
  1796.   redraw=0;
  1797.   MouseHide();
  1798.   max=10;
  1799.   if (numnames<10)
  1800.     max=numnames;
  1801.   for (i=0;i<max;i++)
  1802.     {
  1803.      bar(dx+LISTX,dy+LISTY+i,dx+LISTX+11,dy+LISTY+i,' ');
  1804.      FDoff(dx+LISTX,dy+LISTY+i,i);
  1805.     }
  1806.   MouseShow();
  1807.  
  1808.   //
  1809.   // THIS LOOP CHECKS INPUT
  1810.   //
  1811.   do
  1812.   {
  1813.    select=CheckList(dx+LISTX,dy+LISTY,12,max,FDon,FDoff,0);
  1814.    if (select>=0)
  1815.      {
  1816.       redraw=exit=1;
  1817.       continue;
  1818.      }
  1819.  
  1820.    GetButtonXY(&GPd,0,&sx,&sy);
  1821.    select=CheckList(sx,sy,strlen(GPb.text),1,CancelOn,CancelOff,0);
  1822.    if (!select || keydown[1])
  1823.      {
  1824.       RestoreBackground();
  1825.       while(keydown[1]);
  1826.       clearkeys();
  1827.       return -2;
  1828.      }
  1829.  
  1830.    //
  1831.    // CHECK ARROWS & PGUP/DN
  1832.    //
  1833.    if (keydown[0x48] && base)
  1834.      {
  1835.       base--;
  1836.       redraw=1;
  1837.       if (!keydown[0x1d])
  1838.     while(keydown[0x48]);
  1839.      }
  1840.    else
  1841.    if (keydown[0x50] && base+10<numnames)
  1842.      {
  1843.       base++;
  1844.       redraw=1;
  1845.       if (!keydown[0x1d])
  1846.     while(keydown[0x50]);
  1847.      }
  1848.    else
  1849.    if (keydown[0x49])
  1850.      {
  1851.       base-=10;
  1852.       if (base<0)
  1853.     base=0;
  1854.       redraw=1;
  1855.       if (!keydown[0x1d])
  1856.     while(keydown[0x49]);
  1857.      }
  1858.    else
  1859.    if (keydown[0x51])
  1860.      {
  1861.       base+=10;
  1862.       if (base+10>numnames)
  1863.     base=numnames-10;
  1864.       redraw=1;
  1865.       if (!keydown[0x1d])
  1866.     while(keydown[0x51]);
  1867.      }
  1868.  
  1869.   } while(!redraw);
  1870.  } while(!exit);
  1871.  
  1872.  //
  1873.  // RETURN SELECTION
  1874.  //
  1875.  RestoreBackground();
  1876.  return select+base;
  1877. }
  1878.